package main

import (
	"common/cfgstruct"
	"common/log"
	"common/process"
	"common/run"
	"common/version"
	"encoding/json"
	"euplink"
	"euplink/config"
	"fmt"
	"gateway/api"
	handle2 "gateway/handle"
	report2 "gateway/report"
	"github.com/spf13/cobra"
	"github.com/wuzfei/go-helper/path"
	"go.uber.org/zap"
	"os"
	"path/filepath"
)

type Config struct {
	Euplink config.Config
	Api     api.Config
	Log     log.Config
	Report  report2.Config
}

var (
	cfg Config
)

var (
	configFile string
	rootCmd    = &cobra.Command{
		Use:   "gateway",
		Short: "网关",
	}
	runCmd = &cobra.Command{
		Use:   "run",
		Short: "运行",
		RunE:  cmdRun,
	}
	configCmd = &cobra.Command{
		Use:   "config",
		Short: "查看当前所有配置",
		RunE:  cmdConfig,
	}
	setupCmd = &cobra.Command{
		Use:         "setup",
		Short:       "初始化配置",
		RunE:        cmdSetup,
		Annotations: map[string]string{"type": "setup"},
	}
	versionCmd = &cobra.Command{
		Use:   "version",
		Short: "查看版本信息",
		RunE:  cmdVersion,
	}
)

func main() {
	defaultConfig := path.ApplicationDir("gateway", process.DefaultCfgFilename)
	cfgstruct.SetupFlag(rootCmd, &configFile, "config", defaultConfig, "配置文件")
	//根据环境读取默认配置
	defaults := cfgstruct.DefaultsFlag(rootCmd)
	//当前程序所在目录
	currentDir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	rootDir := cfgstruct.ConfigVar("ROOT", currentDir)
	//设置系统的HOME变量
	envHome := cfgstruct.ConfigVar("HOME", os.Getenv("HOME"))
	rootCmd.AddCommand(runCmd)
	rootCmd.AddCommand(configCmd)
	rootCmd.AddCommand(setupCmd)
	rootCmd.AddCommand(versionCmd)
	process.Bind(runCmd, &cfg, defaults, cfgstruct.ConfigFile(configFile), envHome, rootDir)
	process.Bind(configCmd, &cfg, defaults, cfgstruct.ConfigFile(configFile), envHome, rootDir)
	process.Bind(setupCmd, &cfg, defaults, cfgstruct.ConfigFile(configFile), envHome, cfgstruct.SetupMode(), rootDir)
	process.Bind(versionCmd, &struct{}{}, defaults)
	process.Exec(rootCmd)
}

// cmdRun 运行
func cmdRun(cmd *cobra.Command, args []string) (err error) {
	ctx, _ := process.Ctx(cmd)
	_log := log.NewZapLog(&cfg.Log)
	proj, err := euplink.NewProject(ctx, cfg.Euplink, _log.Named("project"))
	if err != nil {
		panic(err)
	}
	handle := handle2.NewHandle(proj, _log.Named("handle"), cfg.Api.MaxSize)
	apiServer := api.NewServer(_log, &cfg.Api, handle)

	runGroup := run.Group{}
	runGroup.Add(apiServer)
	runGroup.Add(report2.NewService(cfg.Api.Endpoint, cfg.Api.Port, &cfg.Report, _log.Named("report")))

	if err = runGroup.Run(ctx); err != nil {
		_log.Error("app.Run error", zap.Error(err))
	}
	return nil
}

// cmdSetup 初始化数据库
func cmdSetup(cmd *cobra.Command, args []string) error {
	return process.SaveConfig(cmd, configFile)
}

// cmdVersion 查看版本信息
func cmdVersion(cmd *cobra.Command, args []string) error {
	fmt.Println(version.Build.String())
	return nil
}

// cmdConfig 查看系统配置
func cmdConfig(cmd *cobra.Command, args []string) error {
	fmt.Printf("当前运行环境：[%s]\n", cfgstruct.DefaultsType())
	fmt.Println("当前配置文件路径：", configFile)
	output, _ := json.MarshalIndent(cfg, "", " ")
	fmt.Println(string(output))
	return nil
}
